﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MrPoetic.MatLab.Hash
{
    using System.Security.Cryptography;

    public enum HashType
    {
        MD5, SHA1, SHA256, SHA384, SHA512
    }
    public static partial class HashIMPL
    {
        static char[] _16Table { get { return DataMatrix.HexTable; } }

        /// <summary>
        /// 对比特数据进行16bit的高位对齐 `F 2 3 4 3 D` ---> `F2 34 3D` 2位 
        /// 合成一个byte字面值char 不足的高位b用0对齐 `FD3` ---> `0F D3`
        /// </summary>
        /// <param name="bContent">需要转换成 16 进制的字节数组</param>
        /// <returns>乱码替换之后的自然语言MD5表达</returns>
        static internal string _CombinBytes(byte[] bContent)
        {
            char[] chs = new char[bContent.Length * 2];
            for (int i = 0, offset = 0; i < bContent.Length; i++)
            {
                chs[offset++] = _16Table[bContent[i] >> 4 & 0x0f];
                chs[offset++] = _16Table[bContent[i] & 0x0f];
            }
            return new string(chs);
        }

        /// 返回MD5散列算法的16位版本
        public static string ToMD516bit(this string oriStr)
        {
            var startIndex = (oriStr.ToHashString( HashType.MD5 )).Length / 4;
            return oriStr.Substring(startIndex, 16);
        }

        /// 扩展类必须指定统一的编码方式 为了兼容移动端和多国语言 这里使用UTF8
        /// 如果节省带宽 请使用 Encoding.Default(GBK国标码)
        public static string ToHashString(this string originString,HashType type = HashType.MD5)
        {
            // 用某种字符集，对比特数组进行字节码加密
            HashAlgorithm Algorithm = null;
            switch (type)
            {
                case HashType.SHA1:
                    Algorithm = new SHA1CryptoServiceProvider();
                    break;
                case HashType.SHA256:
                    Algorithm = new SHA256CryptoServiceProvider();
                    break;
                case HashType.SHA384:
                    Algorithm = new SHA384CryptoServiceProvider();
                    break;
                case HashType.SHA512:
                    Algorithm = new SHA512CryptoServiceProvider();
                    break;
                case HashType.MD5:
                default:
                    Algorithm = new MD5CryptoServiceProvider();
                    break;
            }
            byte[] HashedCodes = Algorithm.ComputeHash(Encoding.UTF8.GetBytes(originString));
            string rs = _CombinBytes(HashedCodes);
            return rs;
        }

        /// <summary>
        /// 字符混淆算法 Base64 StringEncoding
        /// </summary>
        /// <param name="originString">原始字符串</param>
        /// <returns>加密之后的整体字符串</returns>
        public static string ToBase64String(this string originString)
        {
            return Convert.ToBase64String(Encoding.UTF8.GetBytes(originString));
        }
    }
}
